package crudfx.data;
import java.lang.*;
import java.util.*;
import java.text.*;
/**
 * @profile desktop
 * @author Sergey Surikov
 */
public class StringData{
    public var value:String;
    public function parse(text:String):Void{ value=text; }
    public function gather():String{ return value; }
    }
/**
 * @profile desktop
 * @author Sergey Surikov
 */
public class NumberData{
    public var value:Number;
    public function parse(text:String):Void{
        var numberFormat=NumberFormat.getNumberInstance(Locale.ENGLISH);
        value=0;
        try{
            value=numberFormat.parse(text.replaceAll(",","\\.")).doubleValue();
            //value=numberFormat.parse(text).doubleValue();
        } catch (x){
            x.printStackTrace();
            }
        }
    public function gather():String{
        var d:Double=value;
        var s:String=d.toString();
        return s; }
    }
/**
 * @profile desktop
 * @author Sergey Surikov
 */
public class IntegerData{
    public var value:Integer;
    public function parse(text:String):Void{
        var numberFormat=NumberFormat.getNumberInstance();
        value=0;
        try{
            value=numberFormat.parse(text).intValue();
        } catch (x){
            //x.printStackTrace();
            }
        }
    public function gather():String{
        return value.toString();
        }
    }
/**
 * @profile desktop
 * @author Sergey Surikov
 */
public class BooleanData{
    public var value:Boolean;
    public function parse(text:String):Void{
        var numberFormat=NumberFormat.getNumberInstance();
        value=false;
        if(text == "true") value=true;
        }
    public function gather():String{
        return value.toString();
        }
    }
/**
 * @profile desktop
 * @author Sergey Surikov
 */
public class DataTree {
    public var isAttribute:Boolean=false;
    public var children:DataTree[];
    public var attributes:DataTree[];
    public var parent:DataTree;
    public var text:String="";
    public var name:String="";
    public var stringData:StringData=null;
    public var numberData:NumberData=null;
    public var integerData:IntegerData=null;
    public var booleanData:BooleanData=null;
    public function findAttribute(name:String):DataTree{
        def s:DataTree[]=attributes[ e|e.name == name];
        var r:DataTree=null;
        if(sizeof s > 0){ r=s[0]; }
        return r;
        }
    public function find(name:String):DataTree{
        def s:DataTree[]=children[ e|e.name == name];
        var r:DataTree=null;
        if(sizeof s > 0){ r=s[0]; }
        return r;
        }
    public function a(name:String):DataTree{
        //println(name);
        var r:DataTree=findAttribute(name);
        if(r == null){
            r=DataTree{ name:name text:"?" parent:this };
            insert r into attributes;
            };
        //r.dump();
        return r;
        }
    public function node(name:String):DataTree{
        var r:DataTree=find(name);
        if(r == null){
            r=DataTree{ name:name text:"" parent:this };
            insert r into children;
            };
        return r;
        }
    public function asString(value:String):StringData{
        var r:DataTree=find("");
        if(r==null){
            r=DataTree{ parent:this stringData:StringData{value:value}; };
            insert r into children;
            }
        if(r.stringData == null){
            r.stringData=StringData{};
            r.stringData.parse(r.text);
            }
        return r.stringData;
        }
    public function asBoolean(value:Boolean):BooleanData{
        var r:DataTree=find("");
        if(r==null){
            r=DataTree{ parent:this booleanData:BooleanData{value:value}; };
            insert r into children;
            }
        if(r.booleanData == null){
            r.booleanData=BooleanData{};
            r.booleanData.parse(r.text);
            }
        return r.booleanData;
        }
    public function asNumber(value:Number):NumberData{
        var r:DataTree=find("");
        if(r==null){
            r=DataTree{ parent:this numberData:NumberData{value:value}; };
            insert r into children;
            }
        if(r.numberData == null){
            r.numberData=NumberData{};
            r.numberData.parse(r.text);
            }
        return r.numberData;
        }
    public function asInteger(value:Integer):IntegerData{
        var r:DataTree=find("");
        if(r==null){
            r=DataTree{ parent:this integerData:IntegerData{value:value}; };
            insert r into children;
            }
        if(r.integerData == null){
            r.integerData=IntegerData{};
            r.integerData.parse(r.text);
            }
        return r.integerData;
        }
    public function add(name:String):DataTree{
        var r:DataTree=DataTree{ name:name parent:this };
        insert r into children;
        return r;
        }
    public function drop(name:String):Void{
        var r:DataTree=node(name);
        delete r from children;
        }
    public function reset(name:String):Void{
        for(d:DataTree in children){
            d.reset("");
            //delete d from children;
            }
        delete children;
        this.name=name;
        }
    public function gather():String{
        var cutext:String="";
        if(this.isAttribute){
            if((sizeof children)>0)cutext=children[0].gather();
            }
        else{
            if(stringData!=null){ cutext=stringData.gather(); }
            else if(booleanData!=null){ cutext=booleanData.gather(); }
            else if(numberData!=null){ cutext=numberData.gather(); }
            else if(integerData!=null){ cutext=integerData.gather(); }
            else { cutext=this.text; }
            }
        if(cutext==null)cutext="";
        return cutext;
        }
    public function createCopy():DataTree{
        var root:DataTree=DataTree{
            name:name
            text:gather()
            };
        for(n:DataTree in children)insert n.createCopy() into root.children;
        for(a:DataTree in attributes)insert a.createCopy() into root.attributes;
        return root;
        }
    public function dump():Void{
        dump("");
        }
    function dump(pad:String):Void{
        print("{pad}{name}");
        if((sizeof attributes)>0){
            print("/");
            for(a:DataTree in attributes){
                print("{a.name}={a.gather()}/");
                /*print(a.name);
                for(av:DataTree in a.children)print("={av.gather()}/");*/
                }
            }
        println(":{gather()}");
        for(d:DataTree in children){ d.dump("{pad}_ "); }
        }
    }
